import axios from "axios";

import type {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  InternalAxiosRequestConfig,
} from "axios";

import router from "@/router/index";

import { ElLoading, ElMessage } from "element-plus";

import type { LoadingInstance } from "element-plus/lib/components/loading/src/loading";
//加载loading样式
import "element-plus/es/components/loading/style/css";

//加载message提示样式
import "element-plus/es/components/message/style/css";

//自定义拦截器接口
interface HInterceptor {
  //请求成功拦截器
  requestSuccessFn?: (
    config: InternalAxiosRequestConfig
  ) => InternalAxiosRequestConfig;
  //请求失败拦截器
  requestCatchFn?: (error: any) => any;
  //响应成功拦截器
  responseSuccessFn?: (res: AxiosResponse) => AxiosResponse;
  //响应失败拦截器
  responseCatchFn?: (error: any) => any;
}

//扩展请求拦截器接口
interface HRequestConfig extends AxiosRequestConfig {
  //添加自定义拦截器
  inteceptor?: HInterceptor;
}

//使用class类封装

class HRequest {
  //axios实例成员
  instance: AxiosInstance;
  //loading成员
  loading?: LoadingInstance;
  //自定义拦截器成员
  interceptor?: HInterceptor;

  //构造器初始化操作
  constructor(config: HRequestConfig) {
    //初始化axios实例
    this.instance = axios.create(config);
    //初始化自定义拦截器成员
    this.interceptor = config.inteceptor;

    //单个实例的请求拦截器
    this.instance.interceptors.request.use(
      this.interceptor?.requestSuccessFn,
      this.interceptor?.requestCatchFn
    );

    //单个实例响应拦截器
    this.instance.interceptors.response.use(
      this.interceptor?.responseSuccessFn,
      this.interceptor?.responseCatchFn
    );

    //全局请求拦截器
    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        //loading加载中
        this.loading = ElLoading.service({
          lock: true,
          text: "玩命加载中",
          background: "rgba(0, 0, 0, 0.4)",
        });

        //本项目中除了登录接口之后，其他任何接口必须配置请求头添加token，才能拿到正确结果
        console.log("config:", config);
        if (config.url !== "/login") {
          const token = localStorage.getItem("token");
          token && (config.headers["Authorization"] = token);
        }

        return config;
      },
      (error) => {
        return Promise.reject(error);
      }
    );
    //全局响应拦截器
    this.instance.interceptors.response.use(
      //隐藏loading  loading
      //成功或失败，提示，登录成功，用户名不对  message
      (res) => {
        this.loading?.close();
        //获取msg,status
        const { msg, status } = res.data.meta;
        //定义状态码白名单
        const whiteList = [200, 201, 204];
        if (whiteList.includes(status)) {
          //显示成功提示
          ElMessage({
            type: "success",
            message: msg,
          });

          //如果调用的是登录接口，保存token
          console.log("成功返回的res:::", res);
          if (res.config.url === "/login") {
            //保存token
            localStorage.setItem("token", res.data.data.token);
            //跳转到home
            router.push("/home");
          }

          //返回数据
          return res.data;
        }

        //提示错误信息

        ElMessage({
          type: "error",
          message: msg,
        });
        //返回错误
        return Promise.reject(msg);
      },
      (error) => {
        return Promise.reject(error);
      }
    );
  }

  //封装真正的请求方法
  request<T>(config: HRequestConfig): Promise<T> {
    return new Promise((resolve, reject) => {
      this.instance
        .request<any, T>(config)
        .then((res) => {
          resolve(res);
        })
        .catch((error) => {
          return Promise.reject(error);
        });
    });
  }
}

export default HRequest;
